package gestores;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;
import java.util.Vector;
import java.sql.ResultSet;
import java.sql.SQLException;

import componentes.Competencia;
import componentes.Encuentro;
import componentes.Fixture;
import componentes.Participante;
import componentes.Usuario;
import dao.DAO_Competencia;
import dao.DAO_Encuentros;
import dao.DAO_Lugar;
import dao.DAO_Participante;
import dto.DTOcompetencia;


public class GestorCompetencia {
	private static GestorCompetencia INSTANCE = null;
	/**
     * constructor
     */
    private GestorCompetencia() {
		// TODO Auto-generated constructor stub
	}
    
    
    
    /**
     *  Metodo para obtener una instancia, si existe la devuelve, sino la crea
     * @return instancia si existe
     */
    public static GestorCompetencia getInstance(){
 		if (INSTANCE == null) { 
            INSTANCE = new GestorCompetencia();
            
        }
 		return INSTANCE;
    }
 	

	/**
	 * Este metodo valida el nombre de la competencia.
	 * @param: Nombre de la competencia 
	 * 
	 * @return 0: Indicador nombre valido
	 * @return 1: Indicador nombre invalido debido a que el nombre supera los 35 caracteres
	 * @return 2: Indicador nombre invalido debido a que el nombre ya esta presente en la base de datos
	 * @throws SQLException 
	 */
	public int validarNombreCompetencia(String nombreComp) throws SQLException {
		int retorno = 0;
		
		if(nombreComp.length()>35){
			retorno = 1;
		}
		else if(DAO_Competencia.getInstance().validarNombre(nombreComp).next()){
			retorno = 2;
		}
		
		return retorno;

	}
	
	public Competencia crearCompetencia(DTOcompetencia dtoCompetencia){
		
		Competencia comp= new Competencia(dtoCompetencia);
		return comp;
		
	}

	public void guardarCompetencia(Competencia comp) throws NumberFormatException, SQLException {
		ResultSet deporte;
		int id_deporte;
		deporte = GestorBD.getInstance().ejecutar("SELECT  `id_deporte` FROM  `deporte` WHERE  `deporte`.`nombreDeporte` =  '"+comp.getDeporte()+"' AND `deporte`.`eliminada` =  '0'; ");
		
		//Si devolvio alguna fila la consulta
				if(deporte.next()){
					//Obtiene la primer fila
					
					id_deporte = Integer.parseInt(deporte.getString("id_deporte"));
					DAO_Competencia.getInstance().guardarCompetencia(comp, id_deporte);
				}
		
	}	
	
	

	
	
	
	
	//Verifica si el nombre del participante ya esta usando en la lista de participantes que tiene la competencia
	//Retorna false, si no se encuentra, true si se encuentra
	public boolean verificarExistenciaNombre(Competencia competencia,String nombre) {
		 try {
				return DAO_Participante.getInstance().buscarParticipanteNombre(nombre,String.valueOf(competencia.getId_competencia())).next();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		return false;
	}

	//Verifica si el correo del participante ya esta usando en la lista de participantes que tiene la competencia
	//Retorna false, si no se encuentra, true si se encuentra
		public boolean verificarExistenciaCorreo(Competencia competencia,String correo) {
			 try {
				return DAO_Participante.getInstance().buscarParticipanteCorreo( correo, String.valueOf(competencia.getId_competencia())).next();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			return false;
			
		}
		
		
	//Este metodo agrega el participante pasado como parametro en la competencia
	public void addParticipante(Competencia competencia, Participante participante) {
		competencia.getParticipantes().add(participante);
		DAO_Participante.getInstance().guardarParticipante(participante.getCorreoElectronico(), participante.getNombre(), participante.getImagen(), competencia.getId_competencia());
	
		
		
	}



	/**LLamado de la interfaz verCompetencia.
	 * Recibe un dtoCompetencia incompleto, debe buscar en la BD y completarlo y crear la competencia
	 * @param dtoComp
	 */
	public Competencia completarCompetencia(DTOcompetencia dtoComp) {
		Competencia nuevaCompetencia = null;
		try {
			ResultSet comp= DAO_Competencia.getInstance().buscarcompetencias(dtoComp.getNombre());
			comp.last();
			comp.first();
			String id= comp.getString("id_competencia"); //va al dto?
			dtoComp.setId_usuario(Integer.parseInt(comp.getString("id_usuario")));
			dtoComp.setEstado(comp.getString("estado"));
			dtoComp.setModalidad(comp.getString("tipo_modalidad"));
			dtoComp.setPuntuacion(comp.getString("tipo_puntuacion"));
			dtoComp.setDeporte(comp.getString("nombreDeporte"));
			dtoComp.setReglamento(comp.getString("reglamento"));
			dtoComp.setEmpate(Integer.parseInt(comp.getString("empate")));
					
			if(comp.getString("tipo_puntuacion").equals("Puntuacion") && comp.getString("tipo_modalidad").equals("Liga")){
				
				dtoComp.setGolesAfavor(Integer.parseInt(comp.getString("goles_a_favor")));
				dtoComp.setPuntosPorPartidoGanado(Integer.parseInt(comp.getString("ptos_por_ganar")));
				dtoComp.setPuntosPorPresentarse(Integer.parseInt(comp.getString("ptos_por_presentarse")));
			}
			if(comp.getString("tipo_puntuacion").equals("Sets")){
				dtoComp.setCantDeSets(Integer.parseInt(comp.getString("cant_sets")));
				dtoComp.setPuntosPorPartidoGanado(Integer.parseInt(comp.getString("ptos_por_ganar")));
				dtoComp.setPuntosPorPresentarse(Integer.parseInt(comp.getString("ptos_por_presentarse")));
			}
			if(Integer.parseInt(comp.getString("empate"))==1){
				dtoComp.setPuntosEmpate(Integer.parseInt(comp.getString("ptos_por_empate")));
			}
			
			ResultSet lugares =DAO_Lugar.getInstance().buscarLugares(id);
			lugares.first();
			dtoComp.setLugar(new ArrayList<String>());
			dtoComp.setDisponibilidad(Integer.parseInt(lugares.getString("disponibilidad")));
			dtoComp.getLugar().add(lugares.getString("nombre"));
			
			
			while(lugares.next()){
				dtoComp.setDisponibilidad(dtoComp.getDisponibilidad()+Integer.parseInt(lugares.getString("disponibilidad")));
				dtoComp.getLugar().add(lugares.getString("nombre"));
				
			}
			lugares.close();
			nuevaCompetencia=crearCompetencia(dtoComp);
			nuevaCompetencia.setId_competencia(Integer.parseInt(id));
			
			
		
			ResultSet participantes = DAO_Participante.getInstance().buscarParticipantesCompetencia(id);
			while(participantes.next()){
				nuevaCompetencia.getParticipantes().add(new Participante(participantes.getString("nombre"),participantes.getString("correo"), participantes.getString("imagen")));
			}
		
			
			
			
			
			
			
			
			
			
			
			
			ResultSet encuentros = DAO_Encuentros.getInstance().obtenerEncuentros(id);
		
			Fixture fixture = new Fixture();
			List<List> aux = new ArrayList();
			List<String> lista= new ArrayList();
			Encuentro encuentroAux = null;
			String id_participante1;
			String id_participante2;
			int i=0;
			while(encuentros.next()){
				aux.add(lista);
				encuentroAux = new Encuentro(encuentros.getString("fecha"), encuentros.getString("dia_realizacion"), encuentros.getString("numero_encuentro"), encuentros.getString("id_lugar"), encuentros.getString("tipo_resultado"));
				lista.add(id_participante1 = encuentros.getString(4)); //la columna 1 tiene el indice 1
				lista.add(id_participante2 = encuentros.getString(5));
				aux.add(lista);
								
				fixture.getEncuentros().add(encuentroAux);
			}
			
			for(int j=0;j<fixture.getEncuentros().size();j++){
				fixture.getEncuentros().get(j).setParticipante1(buscarParticipante(nuevaCompetencia.getParticipantes(), aux.get(j).get(0).toString(), id, nuevaCompetencia));
				fixture.getEncuentros().get(j).setParticipante2(buscarParticipante(nuevaCompetencia.getParticipantes(), aux.get(j).get(1).toString(), id, nuevaCompetencia));
			}
			
			
			
			nuevaCompetencia.setFixture(fixture);
			
			
			
			
			//y resultados
			
			
		} catch (SQLException e) {
			e.printStackTrace();
		} 

		return nuevaCompetencia;
	}





	public List<Encuentro> proximosEncuentros(Competencia competencia) {
		
		List<Encuentro> encuentros= competencia.getFixture().getEncuentros();
		
		while(encuentros.size()>0 && encuentros.get(0).estaJugado()){
			encuentros.remove(0);
		}
		return encuentros;
		
	}



	public List<List> BuscarListaCompentecias(String nombre, String modalidad,	String deporte, String estado, Usuario usuarioLogueado ) {
		
		ResultSet competencias;
		int cantDeComp;
		List<List> listacompetencia=new ArrayList<List>();
		
		try{
			competencias=DAO_Competencia.getInstance().buscarCompetencia(nombre, modalidad, deporte, estado, usuarioLogueado.getId_Usuario());		
		    competencias.last();
			cantDeComp=competencias.getRow();
			competencias.first();
		
			for(int i=0; i<cantDeComp ; i++){
				List<String> datos=new ArrayList<String>();
				datos.add(Integer.toString (i+1));
				datos.add(competencias.getString("nombre"));
				datos.add(competencias.getString("nombreDeporte"));
				datos.add(competencias.getString("estado"));
				datos.add(competencias.getString("tipo_modalidad"));
				listacompetencia.add(datos);
				competencias.next();
			}
		
		
		} catch (SQLException e) {
			e.printStackTrace();
		}
		
		return listacompetencia;
	}

	public void eliminarFixture(Competencia competencia) {
		//TODO implementar
		
	}


	public void actualizarEstado(Competencia competencia) {
	//TODO implementar	
		
	}


	public void generarFixture(Competencia competencia){
		
		List<String> lugares=competencia.getLugares();
		int cantPart= competencia.getParticipantes().size();
		int numFechas;
		Date dia= new Date();
		SimpleDateFormat formato = new SimpleDateFormat("dd.MM.yy");
		String cadenaFecha = formato.format(dia);
		
		if(competencia.getEstado().equals("creada")){
			List<Participante> listaPart=ordenarParticipantesAleatoriamente(competencia.getParticipantes());
			if(competencia.getModalidad().equals("Liga")){
				
				if(cantPart%2==0)
					numFechas=cantPart-1;
				else
					numFechas=cantPart;
				
				Vector<Participante> lista1 = new Vector<Participante>();
				Vector<Participante> lista2 = new Vector<Participante>();
				for(int i=0; i<listaPart.size()/2; i++){
					lista1.add(listaPart.get(i));
				}
				for(int i=listaPart.size()-1; i>=listaPart.size()/2; i--){
					lista2.add(listaPart.get(i));
				}
				if(listaPart.size()%2!=0){
					lista2.add(0,new Participante("Libre", "", ""));
				}
				int fecha=1, encuentro;
				while(fecha<=numFechas){
					encuentro=1;
					for(int i=0; i<lista1.size(); i++){ //genero la primer fecha
						String lugar=buscarLugarDisponible(lugares, cadenaFecha);
						competencia.getFixture().getEncuentros().add(GestorEncuentro.getInstance().generarEncuentro(lista1.get(i), lista2.get(i), fecha, encuentro, lugar, competencia.getModalidad().getPuntuacion().getTipo()));
						encuentro++;
					}
					Participante aux= lista1.remove(lista1.size()-1);
					lista2.add(aux);
					lista1.add(1, lista2.get(0));
					lista2.remove(0);
					fecha++;
				}//fin de crear las fechas

			}
			if(competencia.getModalidad().equals("Eliminatoria Simple")){
				// NO IMPLEMENTAR
			}
			
			if(competencia.getModalidad().equals("Eliminatoria Doble")){
				// NO IMPLEMENTAR	
			}
		}
	}
	
	private String buscarLugarDisponible(List<String> lugares, String fecha) {
		int i=0;
		String lugar= lugares.get(i);
		 while(GestorLugares.getInstance().disponibilidad(lugar, fecha)==0){
			 i++;
			 lugar= lugares.get(i);
		 }
		 GestorLugares.getInstance().setearDisponibiliadd(lugar, fecha);
		 
		return lugar;
	}



	private List<Participante> ordenarParticipantesAleatoriamente(List<Participante> participantes) {
		List<Participante> nuevaLista= new ArrayList<Participante>();
		int n = participantes.size();
		int k = n;
		int[] resultado = new int[n];
		int[] numeros=new int[n];       
		Random rnd = new Random();
		int res;
		       
		for(int i=0;i<n;i++){
		    numeros[i]=i;
		}
		       
		for(int i=0;i<n;i++){
		    res = rnd.nextInt(k);           
		        resultado[i]=numeros[res];
		        numeros[res]=numeros[k-1];
		        k--;           
		}
		for(int i = 0; i<10; i++){
		       nuevaLista.add(participantes.get(resultado[i]));
		}
		return nuevaLista;
	}
	
	
	public int[][] mostrarTablaPosiciones(Competencia competencia){
		
		if(competencia.getModalidad().equals("Liga") && (competencia.getEstado().equals("En Disputa") || (competencia.getEstado()=="Finalizada"))){
			/*HAY QUE CALCULAR LOS PNTOS DE CADA PARTICIPANTE*/
			
			String puntuacion= competencia.getModalidad().getPuntuacion().getTipo();
			if(puntuacion.equals("Puntuacion")){
				return calcularParaPuntuacion(competencia);
			}
			if(puntuacion.equals("Final")){
				calcularParaFinal();
			}
			if(puntuacion.equals("Sets")){
				calcularParaSets();
			}
			
		}
		return new int[0][0];
	}



	private void calcularParaSets() {
		// TODO: implementar para tabla por sets
		
	}



	private void calcularParaFinal() {
		// TODO: implementar para tabla por final
		
	}



	private int[][] calcularParaPuntuacion(Competencia competencia) {
		int[][] lista_aux = new int[competencia.getParticipantes().size()][8]; //matriz de datos
		List<Encuentro> encuentros=competencia.getFixture().getEncuentros();
		List<Participante> participantes = competencia.getParticipantes();
		
		for(int i=0; i<encuentros.size() && encuentros.get(i).estaJugado() ;i++){
			String part1=encuentros.get(i).getParticipante1().getNombre();
			String part2= encuentros.get(i).getParticipante2().getNombre();
			
			if(encuentros.get(i).getResultado().ganador().compareTo("Participante 1")==0){
				String nombreGanador= part1;
				int j=0;
				while(!participantes.get(j).getNombre().equals(nombreGanador)){ //busco el indice del part1
					j++;
				}
				int indice=participantes.indexOf(participantes.get(j));
				//cargo datos del resultado del encuentro
				lista_aux[indice][1]+=competencia.getPuntosPorPartidoGanado();
				lista_aux[indice][2]+=1;
				lista_aux[indice][5]+=encuentros.get(i).getResultado().tantosPart1();
				lista_aux[indice][6]+=encuentros.get(i).getResultado().tantosPart2();
				lista_aux[indice][7]+=(lista_aux[indice][5]-lista_aux[indice][6]);
				
				j=0;
				while(!participantes.get(j).getNombre().equals(part2)){ //busco el indice del part2
					j++;
				}
				indice=participantes.indexOf(participantes.get(j));
				lista_aux[indice][4]+=1;
				lista_aux[indice][5]+=encuentros.get(i).getResultado().tantosPart2();
				lista_aux[indice][6]+=encuentros.get(i).getResultado().tantosPart1();
				lista_aux[indice][7]+=(lista_aux[indice][5]-lista_aux[indice][6]);
			}
			
			if(encuentros.get(i).getResultado().ganador().compareTo("Participante 2")==0){
				String nombreGanador= part2;
				int j=0;
				while(!participantes.get(j).getNombre().equals(nombreGanador)){ //busco el indice del part2
					j++;
				}
				int indice=participantes.indexOf(participantes.get(j));
				//cargo datos del resultado del encuentro
				lista_aux[indice][1]+=competencia.getPuntosPorPartidoGanado();
				lista_aux[indice][2]+=1;
				lista_aux[indice][5]+=encuentros.get(i).getResultado().tantosPart2();
				lista_aux[indice][6]+=encuentros.get(i).getResultado().tantosPart1();
				lista_aux[indice][7]+=(lista_aux[indice][5]-lista_aux[indice][6]);
				
				j=0;
				while(!participantes.get(j).getNombre().equals(part2)){ //busco el indice del part1
					j++;
				}
				indice=participantes.indexOf(participantes.get(j));
				lista_aux[indice][4]+=1;
				lista_aux[indice][5]+=encuentros.get(i).getResultado().tantosPart1();
				lista_aux[indice][6]+=encuentros.get(i).getResultado().tantosPart2();
				lista_aux[indice][7]+=(lista_aux[indice][5]-lista_aux[indice][6]);
			}
			
			if(encuentros.get(i).getResultado().ganador().compareTo("Empate")==0){
				int j=0;
				while(!participantes.get(j).getNombre().equals(part1)){ //busco el indice del part1
					j++;
				}
				int indice=participantes.indexOf(participantes.get(j));
				//cargo datos del resultado del encuentro
				lista_aux[indice][1]+=competencia.getPuntosEmpate();
				lista_aux[indice][3]+=1;
				lista_aux[indice][5]+=encuentros.get(i).getResultado().tantosPart1();
				lista_aux[indice][6]+=encuentros.get(i).getResultado().tantosPart2();
				lista_aux[indice][7]+=(lista_aux[indice][5]-lista_aux[indice][6]);
				
				j=0;
				while(!participantes.get(j).getNombre().equals(part2)){ //busco el indice del part2
					j++;
				}
				indice=participantes.indexOf(participantes.get(j));
				lista_aux[indice][1]+=competencia.getPuntosEmpate();
				lista_aux[indice][3]+=1;
				lista_aux[indice][5]+=encuentros.get(i).getResultado().tantosPart2();
				lista_aux[indice][6]+=encuentros.get(i).getResultado().tantosPart1();
				lista_aux[indice][7]+=(lista_aux[indice][5]-lista_aux[indice][6]);
			}
			
			
		}
		
	return lista_aux;
	}
	
	
	

	private Participante buscarParticipante(List<Participante> participantes, String id_participante, String id_competencia , Competencia comp) throws SQLException {
		// TODO Auto-generated method stub
	
		ResultSet participante = GestorParticipante.getInstance().getCorreo(id_participante, id_competencia );
		participante.first();
		
		String correoPart = participante.getString("correo");
		int i =0;
		while(i<comp.getParticipantes().size() && !comp.getParticipantes().get(i).getCorreoElectronico().equals(correoPart)){
			i++;
			
		}
		
		
		return comp.getParticipantes().get(i);
	}

	
	}
	
	

